﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.XPath;
using System.Xml;
using System.Globalization;
using System.Reflection;
using System.Security.AccessControl;

namespace ParseXAML
{
    /// <summary>
    /// Resource generator
    /// </summary>
    internal static class ResxGenerator
    {
        #region Internal methods

        internal static void SaveResourceFile(Global global, string filename, ICollection<ResourceDataItem> items)
        {
            if (File.Exists(filename))
            {
                ResxGenerator.MergeExistingResourceFile(global, filename, items);
            }
            else
            {
                ResxGenerator.CreateNewResourceFile(global, filename, items);
            }
        }

        /// <summary>
        /// Create a new resource file and add the items to it.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="filename">Name of the resource file.</param>
        /// <param name="items">Items to be added.</param>
        internal static void CreateNewResourceFile(Global global, string filename, ICollection<ResourceDataItem> items)
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            using (Stream emptyResource = currentAssembly.GetManifestResourceStream("ParseXAML.TemplateResx"))
            {
                XmlDocument document = new XmlDocument();
                document.Load(emptyResource);

                XmlNode node = document.SelectSingleNode("root");
                AddNewItems(global, document, node, items);

                string directory = Path.GetDirectoryName(filename);
                if (!Directory.Exists(directory))
                {
                    DirectoryInfo di = Directory.CreateDirectory(directory);
                    if ((di.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                    {
                        di.Attributes ^= FileAttributes.ReadOnly;
                    }
                }

                document.Save(filename);
            }
        }

        /// <summary>
        /// Get an existing resource file and merge the items with it.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="filename">Name of the resource file.</param>
        /// <param name="items">Items to be merged.</param>
        internal static void MergeExistingResourceFile(Global global, string filename, ICollection<ResourceDataItem> items)
        {
            XmlDocument document = new XmlDocument();
            document.Load(filename);

            XmlNode node = document.SelectSingleNode("root");
            bool changed = AddNewItems(global, document, node, items);

            if (changed)
            {
                document.Save(filename);
            }
        }

        #endregion

        #region Private methods

        private static bool AddNewItems(Global global, XmlDocument document, XmlNode rootNode, ICollection<ResourceDataItem> items)
        {
            bool changed = false;
            foreach (ResourceDataItem item in items)
            {
                XmlNode existingnode = rootNode.SelectSingleNode("data[@name='" + item.ResourceKey + "']");
                if (existingnode == null)
                {
                    AddNewItem(global, document, rootNode, item);
                    global.AddLogMessage(LogMessage.eType.ResXAdd, Trans.AddResX, item.ResourceKey, item.ResourceValue);
                    changed = true;
                }
                else
                {
                    existingnode = existingnode.SelectSingleNode("value");
                    if ((existingnode != null ) && existingnode.InnerText != item.ResourceValue)
                    {
                        global.AddLogMessage(LogMessage.eType.ResXModify, Trans.ChangeResX, item.ResourceKey, existingnode.InnerText, item.ResourceValue);
                        if (global.UpdateResX)
                        {
                            existingnode.InnerText = item.ResourceValue;
                            changed = true;
                        }
                    }
                }
            }
            return changed;
        }

        private static void AddNewItem(Global global, XmlDocument document, XmlNode rootNode, ResourceDataItem item)
        {
            XmlElement newDataItem = document.CreateElement("data");
            XmlAttribute nameAttr = document.CreateAttribute("name");
            nameAttr.Value = item.ResourceKey;
            XmlAttribute preserveSpace = document.CreateAttribute("xml:space");
            preserveSpace.Value = "preserve";

            newDataItem.Attributes.Append(nameAttr);
            newDataItem.Attributes.Append(preserveSpace);

            XmlElement newDataValue = document.CreateElement("value");
            if (!string.IsNullOrEmpty(item.ResourceValue))
            {
                newDataValue.AppendChild(document.CreateTextNode(item.ResourceValue));
            }

            newDataItem.AppendChild(newDataValue);
            rootNode.AppendChild(newDataItem);
        }

        #endregion
    }
}
